Skip to content

USB Host: integrate class API [3: UVC]#94591

Merged
MaureenHelm merged 4 commits intozephyrproject-rtos:mainfrom
josuah:pr_usb_host_class_api3
Feb 9, 2026
Merged

USB Host: integrate class API [3: UVC]#94591
MaureenHelm merged 4 commits intozephyrproject-rtos:mainfrom
josuah:pr_usb_host_class_api3

Conversation

@josuah
Copy link
Copy Markdown
Contributor

@josuah josuah commented Aug 17, 2025

Dependency:

Downstream:

NOTE: this PR also contains the commit of #94504 and #94590

On top of the commits from the previous PRs:

  • split UVC helpers out of the device stack so that they can be used with the host stack.

UVC Device still works:

west build --build-dir build-uvc -b nrf52840dk/nrf52840 -S video-sw-generator samples/subsys/usb/uvc/

mpv-shot0001

All tests are done on top of main...josuah:zephyr:pr_usb_host_class_api3

@sonarqubecloud
Copy link
Copy Markdown

sonarqubecloud Bot commented Sep 4, 2025

Quality Gate Failed Quality Gate failed

Failed conditions
E Reliability Rating on New Code (required ≥ C)

See analysis details on SonarQube Cloud

Catch issues before they fail your Quality Gate with our IDE extension SonarQube for IDE

@josuah josuah force-pushed the pr_usb_host_class_api3 branch from 6a5c7fc to 71cb2cf Compare October 9, 2025 21:23
@josuah josuah force-pushed the pr_usb_host_class_api3 branch 4 times, most recently from 2fd3ae8 to a38c550 Compare October 30, 2025 00:49
@josuah
Copy link
Copy Markdown
Contributor Author

josuah commented Oct 30, 2025

Force-push:

  • Fix some CI errors
  • re-base on top of recent API2 PR
  • integrate tests for the class filtering API

@josuah josuah force-pushed the pr_usb_host_class_api3 branch 2 times, most recently from cb1281f to c1c99ae Compare October 30, 2025 18:52
@josuah
Copy link
Copy Markdown
Contributor Author

josuah commented Oct 30, 2025

The UVC implementation there is a stub, does not provide anything useful besides logging the descriptors.

The purpose is to show how to implement basic descriptors access and how to use unit tests on host+device class together.

@josuah josuah marked this pull request as ready for review October 30, 2025 21:15
@zephyrbot zephyrbot added area: Devicetree area: Devicetree Bindings area: Boards/SoCs area: USB Universal Serial Bus area: Tests Issues related to a particular existing or missing test labels Oct 30, 2025
@josuah josuah force-pushed the pr_usb_host_class_api3 branch from afacd3c to 20bea4e Compare February 2, 2026 20:47
@josuah
Copy link
Copy Markdown
Contributor Author

josuah commented Feb 2, 2026

The PR #103369 got split out of this one, as it could be submitted directly on top of main.
It is now a dependency.

Comment thread subsys/usb/host/class/usbh_uvc.c Outdated
* SPDX-License-Identifier: Apache-2.0
*/

#define DT_DRV_COMPAT zephyr_uvc_host
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using DT just to be able to instantiate is a kind of abuse. UVC class driver is not something that needs to be described or configured with DT. I do not like it in the device part, and even less here. Since it is only about supporting a hardcoded number of UVC functions, and there is nothing else to configure, we should use LISTIFY macro as in usb/subsys/device_next/class/loopback.c. Below is a working draft:

diff --git a/subsys/usb/host/class/Kconfig.uvc b/subsys/usb/host/class/Kconfig.uvc
index 39e652f7a04..79083523a73 100644
--- a/subsys/usb/host/class/Kconfig.uvc
+++ b/subsys/usb/host/class/Kconfig.uvc
@@ -2,17 +2,16 @@
 # SPDX-License-Identifier: Apache-2.0
 
 config USBH_VIDEO_CLASS
-	bool "USB Video Class implementation [EXPERIMENTAL]"
-	depends on DT_HAS_ZEPHYR_UVC_HOST_ENABLED
+	bool "USB host Video Class support [EXPERIMENTAL]"
 	select EXPERIMENTAL
 	help
 	  USB Host Video Class (UVC) implementation.
 
 if USBH_VIDEO_CLASS
 
-module = USBH_VIDEO
+module = USBH_UVC
 module-str = usbh uvc
 default-count = 1
 source "subsys/logging/Kconfig.template.log_config"
-
+source "subsys/usb/device_next/class/Kconfig.template.instances_count"
 endif # USBH_VIDEO_CLASS
diff --git a/subsys/usb/host/class/usbh_uvc.c b/subsys/usb/host/class/usbh_uvc.c
index 228b9c5f027..944e64d48ae 100644
--- a/subsys/usb/host/class/usbh_uvc.c
+++ b/subsys/usb/host/class/usbh_uvc.c
@@ -3,12 +3,10 @@
  * SPDX-License-Identifier: Apache-2.0
  */
 
-#define DT_DRV_COMPAT zephyr_uvc_host
-
 #include <stdlib.h>
 
 #include <zephyr/init.h>
-#include <zephyr/devicetree.h>
+#include <zephyr/device.h>
 #include <zephyr/kernel.h>
 #include <zephyr/sys/byteorder.h>
 #include <zephyr/sys/atomic.h>
@@ -19,7 +17,6 @@
 #include <zephyr/drivers/video-controls.h>
 #include <zephyr/logging/log.h>
 
-#include <zephyr/devicetree.h>
 #include <zephyr/sys/util.h>
 #include <zephyr/usb/usb_ch9.h>
 
@@ -32,10 +29,10 @@
 #include "../../../drivers/video/video_ctrls.h"
 #include "../../../drivers/video/video_device.h"
 
-LOG_MODULE_REGISTER(usbh_uvc, CONFIG_USBH_VIDEO_LOG_LEVEL);
+LOG_MODULE_REGISTER(usbh_uvc, CONFIG_USBH_UVC_LOG_LEVEL);
 
 struct usbh_uvc_data {
-	int todo;
+	const char *name;
 };
 
 /*
@@ -123,18 +120,23 @@ static struct usbh_class_filter usbh_uvc_filters[] = {
 	{0},
 };
 
-#define USBH_VIDEO_DT_DEVICE_DEFINE(n)						\
-	struct usbh_uvc_data usbh_uvc_data_##n = {				\
+
+#define USBH_VIDEO_DEVICE_DEFINE(n, _)						\
+										\
+	static struct usbh_uvc_data uvc_data_##n = {				\
+		.name = "uvc_"#n,						\
 	};									\
 										\
-	USBH_DEFINE_CLASS(uvc_c_data_##n, &uvc_class_api,			\
-			  (void *)DEVICE_DT_INST_GET(n), usbh_uvc_filters);	\
+	DEVICE_DEFINE(usbh_uvc_##n, "usbh_uvc_"#n,				\
+		      usbh_uvc_preinit,	NULL,					\
+		      &uvc_data_##n, NULL,					\
+		      POST_KERNEL, CONFIG_VIDEO_INIT_PRIORITY,			\
+		      &uvc_video_api);						\
 										\
-	DEVICE_DT_INST_DEFINE(n, usbh_uvc_preinit, NULL,			\
-			      &usbh_uvc_data_##n, NULL,				\
-			      POST_KERNEL, CONFIG_VIDEO_INIT_PRIORITY,		\
-			      &uvc_video_api);					\
+	USBH_DEFINE_CLASS(uvc_c_data_##n, &uvc_class_api,			\
+			  (void *)DEVICE_GET(usbh_uvc_##n),			\
+			  usbh_uvc_filters);					\
 										\
-	VIDEO_DEVICE_DEFINE(uvc_host_##n, DEVICE_DT_INST_GET(n), NULL);
+	VIDEO_DEVICE_DEFINE(uvc_host_##n, DEVICE_GET(usbh_uvc_##n), NULL);
 
-DT_INST_FOREACH_STATUS_OKAY(USBH_VIDEO_DT_DEVICE_DEFINE)
+LISTIFY(CONFIG_USBH_UVC_INSTANCES_COUNT, USBH_VIDEO_DEVICE_DEFINE, ())
diff --git a/tests/subsys/usb/uvc/boards/native_sim.overlay b/tests/subsys/usb/uvc/boards/native_sim.overlay
index b406fbf404e..09c922c3a7b 100644
--- a/tests/subsys/usb/uvc/boards/native_sim.overlay
+++ b/tests/subsys/usb/uvc/boards/native_sim.overlay
@@ -19,8 +19,4 @@
 	uvc_device: uvcd {
 		compatible = "zephyr,uvc-device";
 	};
-
-	uvc_host: uvch {
-		compatible = "zephyr,uvc-host";
-	};
 };
diff --git a/tests/subsys/usb/uvc/src/main.c b/tests/subsys/usb/uvc/src/main.c
index bcb4040415d..cb6a47b2f17 100644
--- a/tests/subsys/usb/uvc/src/main.c
+++ b/tests/subsys/usb/uvc/src/main.c
@@ -26,6 +26,12 @@ const struct device *const video_dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_camera));
 
 ZTEST(uvc_test, test_virtual_device_virtual_host)
 {
+	const struct device *uvc_dev;
+
+	uvc_dev = device_get_binding("usbh_uvc_0");
+	zassert_not_null(uvc_dev, "No USB host UVC instance available");
+	LOG_INF("%s", uvc_dev->name);
+
 	/* TODO: test the video devices here. */
 }

Copy link
Copy Markdown
Contributor Author

@josuah josuah Feb 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you. I imported these changes and dispatched them into the respective commits, then am now fixing CI again (for a modification I did in #103369).

I do not see anything in UVC device/host that requires devicetree except maybe chosen { zephyr,camera = &uvc_host_0; }; not possible anymore.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please remove dts/bindings/usb/zephyr,uvc-host.yaml.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just removed it. I also rebased it on latest #103369.

@josuah josuah force-pushed the pr_usb_host_class_api3 branch 2 times, most recently from 0bf615e to 8435907 Compare February 3, 2026 02:39
@josuah josuah marked this pull request as ready for review February 3, 2026 02:50
@josuah josuah force-pushed the pr_usb_host_class_api3 branch 4 times, most recently from 0108630 to 63b2278 Compare February 4, 2026 00:38
@josuah
Copy link
Copy Markdown
Contributor Author

josuah commented Feb 4, 2026

My bad, rebase didn't do what I thought it would... Fixing this.

@josuah
Copy link
Copy Markdown
Contributor Author

josuah commented Feb 5, 2026

force-push just to reformat a commit message (was inaccurate after changes)

Comment thread subsys/usb/common/uvc.h
Comment thread subsys/usb/common/uvc.h
Josuah Demangeon added 2 commits February 6, 2026 14:27
Loop through each of the VideoStreaming and VideoControl descriptor
to parse them. This is meant as a stub for the purpose of testing the
class API.

Signed-off-by: Josuah Demangeon <josuah.demangeon@nordicsemi.no>
Add a test to run the USB Video Class host support by using
the existing Zephyr USB Video Class device support.
This allows running implementing the host side from the device side.
A draft implementation of UVC is added leveraging this test.

Signed-off-by: Josuah Demangeon <josuah.demangeon@nordicsemi.no>
@josuah
Copy link
Copy Markdown
Contributor Author

josuah commented Feb 6, 2026

Rebase on top of main

Comment thread subsys/usb/common/Kconfig Outdated
Josuah Demangeon and others added 2 commits February 6, 2026 19:31
Compute the maximum of the CONFIG_USBD_VIDEO_MAX_FRMIVAL and
CONFIG_USBH_VIDEO_MAX_FRMIVAL for struct definition, so that
the same struct can be relevant for both host and device
implementation.

Signed-off-by: Josuah Demangeon <josuah.demangeon@nordicsemi.no>
Signed-off-by: Aiden Hu <weiwei.hu@nxp.com>
Co-authored-by: Aiden Hu <weiwei.hu@nxp.com>
Add input terminal descriptor and CS descriptor header and
extend frame descriptor fields (buffer size, default interval)

Signed-off-by: Aiden Hu <weiwei.hu@nxp.com>
Co-authored-by: Aiden Hu <weiwei.hu@nxp.com>
Signed-off-by: Josuah Demangeon <josuah.demangeon@nordicsemi.no>
@sonarqubecloud
Copy link
Copy Markdown

sonarqubecloud Bot commented Feb 6, 2026

Copy link
Copy Markdown
Member

@carlescufi carlescufi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Skeleton looks fine to me.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: Tests Issues related to a particular existing or missing test area: USB Universal Serial Bus

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants